Skip to content

Add live group standings tab to the tournament page - #4

Merged
borland667 merged 1 commit into
mainfrom
feat/tournament-standings
Jun 15, 2026
Merged

Add live group standings tab to the tournament page#4
borland667 merged 1 commit into
mainfrom
feat/tournament-standings

Conversation

@borland667

Copy link
Copy Markdown
Owner

Summary

Adds a Groups | Standings | Knockout tab nav on the tournament page and a new Standings tab that mirrors the official FIFA standings layout — one FIFA-style table per group with P / W / D / L / GF / GA / GD / Pts, sorted by points → goal difference → goals for → team name.

The view exposes a Live results vs My picks toggle for signed-in participants. The picks view reuses the same table layout but only populates rank + team name (predictions store finishing order, not score lines).

No schema or API changes are required — Match.homeScore, awayScore, status, and homeLabel/awayLabel are already populated by the results importer.

What changed

  • New pure utility src/utils/standings.js
    • computeGroupStandings(group, matches) — derives the 8-column FIFA-style row per team
    • computePredictedGroupStandings(group, prediction) — projects a user's first/second/third onto the same shape
  • tests/standings.test.js — 9 unit cases (empty, partial, full, draw, tiebreakers, foreign matches, partial picks)
  • src/pages/Tournament.jsx
    • new tab nav (Groups | Standings | Knockout) above the existing structure sections
    • new Standings section: per-group cards with FIFA-style tables and the Live / Picks toggle
    • existing Groups and Knockout sections wrapped in tab-aware conditionals
  • src/index.css — design-system styles for the view tabs, the standings toggle, and the per-group standings table (dark + light themes, responsive 1/2/3-column grid matching the groups grid)
  • i18n: tournament.knockout, tournament.standingsViewActual, tournament.standingsViewPicks, tournament.standingsPicksNote, tournament.standingsEmpty, and the tournament.standingsTable.* column headers (short + full) added in en / es / pt / it / nl with each language's canonical sports abbreviations (PJ/G/E/P in Spanish, J/V/E/D in Portuguese, PG/V/N/P in Italian, GS/W/G/V in Dutch, P/W/D/L in English).
  • Docs: IMPLEMENTATION_STATUS.md and QA_CHECKLIST.md updated to reflect the new view.

Test plan

  • npm run verify (lint + db:generate + db:validate + node --test + vite build) — all green locally
  • 9 new unit tests cover: all-zero baseline, ignoring unscored matches, mixed W/D/L row math, multi-tiebreaker sort (points → GD → GF → name), goals-for tiebreaker, foreign-group matches dropped, full prediction ranking, missing prediction (alphabetical), partial / unknown prediction ids
  • Manual smoke: open seeded World Cup 2026, switch through the three tabs, confirm zeroed standings until results arrive, then re-run npm run import:results and confirm the table updates

Made with Cursor

Introduce a Groups | Standings | Knockout tab nav on the tournament
page, modeled after the FIFA tournament-standings layout. The new
Standings tab renders one FIFA-style table per group with P / W / D /
L / GF / GA / GD / Pts, derived directly from finished match scores
that the results importer already persists. Before any matches are
played the table shows the same zeroed baseline as fifa.com.

The view also exposes a Live results vs. My picks toggle for signed-in
participants. The picks view reuses the table layout but populates only
rank and team name, because predictions store finishing order, not
score lines.

No schema or API changes are required: the data this needs already
lives in Match.homeScore, awayScore, status, and homeLabel/awayLabel.
Standings derivation is a new pure utility (computeGroupStandings,
computePredictedGroupStandings) with unit coverage for the empty,
partial, full, draw, and tiebreaker cases.

i18n keys land in en / es / pt / it / nl, using each language's
canonical column abbreviations.

Co-authored-by: Cursor <cursoragent@cursor.com>
@borland667
borland667 merged commit 3de1195 into main Jun 15, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant